package com.by.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.by.bean.PayInfo;
import com.by.bean.PayRequest;
import com.by.bean.PayResponse;
import com.by.client.PaymentClient;
import com.by.client.factory.PaymentClientFactory;
import com.by.entity.Order;
import com.by.mapper.PaymentMapper;
import com.by.service.OrderService;
import com.by.service.PaymentService;
import org.apache.commons.codec.digest.HmacUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    PaymentMapper paymentMapper;

    @Autowired
    private PaymentClientFactory paymentClientFactory; // 支付客户端工厂

    @Autowired
    OrderService orderService;


    @Override
    @Transactional
    public PayResponse createPayment(PayRequest request) {
        // 1. 生成唯一交易流水号（幂等性校验）
        String tradeSn = generateTradeSn(request.getOrderSn());
        // 2. 调用第三方支付接口
        PaymentClient paymentClient = paymentClientFactory.getClient(request.getPaymentMethod());
        PayResponse response = paymentClient.unifiedOrder(request.getAmount(), tradeSn);
        // 3. 保存支付记录
        PayInfo payInfo = buildPayInfo(request, tradeSn, response);
        paymentMapper.savePayInfo(payInfo);

        return response;
    }


    // 生成交易流水号（示例：时间戳+业务单号哈希）
    private String generateTradeSn(String orderSn){
        return DigestUtils.md5DigestAsHex((orderSn+System.currentTimeMillis()).getBytes());
    }

    // 构建支付记录实体
    private PayInfo buildPayInfo(PayRequest request,String tradeSn, PayResponse response){
        PayInfo payInfo = new PayInfo();
        payInfo.setTradeSn(tradeSn);
        payInfo.setSn(request.getOrderSn());
        payInfo.setPayOrderNo(response.getPayOrderNo());
        payInfo.setPaymentMethod(request.getPaymentMethod());
        payInfo.setPayStatus(0);
        payInfo.setFlowPrice(request.getAmount());
        payInfo.setClientType(request.getClientType());
        payInfo.setCreateTime(new Date());
        return payInfo;
    }

    @Override
    public void handlePaymentNotify(Map<String, String> params,String paymentMethod) {
        // 1. 验签（确保请求来自支付宝/微信）
        boolean isSignatureValid = verifySignature(params,paymentMethod);
        if (!isSignatureValid) {
            throw new RuntimeException("签名验证失败");
        }

        // 2. 解析支付结果
        String orderId = params.get("out_trade_no"); // 商户订单号
        String tradeStatus = params.get("trade_status"); // 支付宝状态（如 TRADE_SUCCESS）
        String returnCode = params.get("return_code"); // 微信状态（如 SUCCESS）

        // 3. 幂等性校验（避免重复处理同一笔订单）
        Order order = orderService.getOrderById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        if (order.getPayStatus()==1) {
            return; // 已处理过，直接返回
        }

        // 4. 更新订单状态（根据支付平台状态）
        if ("TRADE_SUCCESS".equals(tradeStatus) || "SUCCESS".equals(returnCode)) {
            orderService.updateOrderStatus(orderId, order.getOrderStatus());
            // 触发后续业务逻辑（如发货、通知用户等）
        } else {
            throw new RuntimeException("支付失败：" + params.get("err_code_des"));
        }
    }

    // 验签方法（直接按渠道处理）
    private boolean verifySignature(Map<String, String> params, String paymentMethod) {
        if ("ALIPAY".equalsIgnoreCase(paymentMethod)) {
            return verifyAlipaySignature(params);
        } else if ("WECHAT".equalsIgnoreCase(paymentMethod)) {
            return verifyWechatSignature(params);
        }
        throw new RuntimeException("不支持的支付渠道");
    }

    // 判断支付渠道（根据参数特征）
    private String determinePaymentMethod(Map<String, String> params) {
        if (params.containsKey("trade_status")) {
            return "ALIPAY";
        } else if (params.containsKey("return_code")) {
            return "WECHAT";
        }
        throw new RuntimeException("无法识别支付渠道");
    }

    // 支付宝验签
    private boolean verifyAlipaySignature(Map<String, String> params) {
        try {
            // 1. 获取支付宝公钥（需从配置或数据库读取）
            String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg+5fmF9qUVy1q6/3xk54iP18bke5myPPFOo4vyxQI9E/v6BUJtn62HEZ8h0PVROUBYiY+hfc0tlp0G5xpC8LdWPBh6KgMaTWYnRlfH9yCJzDqCo5H9XrEL4U3dCNOgDSzFPtac9GYXdJTXlR7by76RIGj6Zf8l3jbMHbuN88E4zbRTjuXaeK7Vvb5zVMD8TWBet1noJJLip+4Mn5yNjQkZC/Xfxy9Dxi8KosS0qsp872Ndt4h42ocTtoYvMeDz7Fmx9wsU3poBQo6ZDdUAakpK+tvBu1BppYsJZHZjilyE6zH3GQN9sUhybR057O4diMJsSdY+JHcvD6kcGqLWTxSQIDAQAB"; // 替换为实际公钥

            // 2. 调用支付宝 SDK 验签
            return AlipaySignature.rsaCheckV1(
                    params,
                    alipayPublicKey,
                    "UTF-8",      // 支付宝回调参数编码
                    "RSA2"        // 签名类型（必须与商户私钥类型一致）
            );
        } catch (AlipayApiException e) {
            throw new RuntimeException("支付宝验签异常", e);
        }
    }

    private boolean verifyWechatSignature(Map<String, String> params) {
        // 1. 获取微信 API 密钥（商户平台配置）
        String wechatApiKey = "your_wechat_api_key";

        // 2. 获取微信回调中的签名
        String receivedSign = params.get("sign");

        // 3. 生成本地签名
        String generatedSign = generateWechatSign(params, wechatApiKey);

        // 4. 对比签名
        return generatedSign.equalsIgnoreCase(receivedSign);
    }

    // 生成微信签名
    private String generateWechatSign(Map<String, String> params, String apiKey) {
        // 1. 过滤空值参数并排序
        Map<String, String> sortedParams = new TreeMap<>(params);
        sortedParams.entrySet().removeIf(entry ->
                entry.getValue() == null || entry.getValue().isEmpty() || "equals(entry.getKey())".equals(entry.getKey())
        );

        // 2. 拼接键值对
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        sb.append("key=").append(apiKey);

        // 3. 计算 MD5/HMAC-SHA256
        String signType = params.getOrDefault("sign_type", "MD5");
        if ("MD5".equalsIgnoreCase(signType)) {
            return DigestUtils.md5DigestAsHex(sb.toString().getBytes()).toUpperCase();
        } else if ("HMAC-SHA256".equalsIgnoreCase(signType)) {
            return HmacUtils.hmacSha256Hex(apiKey, sb.toString()).toUpperCase();
        }
        throw new RuntimeException("不支持的微信签名类型: " + signType);
    }
}
